﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.ComponentModel;
using System.Web.UI.Design;
using TA.Turbo.Design;


namespace TA.Turbo.Controls
{
	/// <summary>
	/// Displays contents upon request, preserving bandwidth by not rendering them during initial render.
	/// </summary>
	[Designer(typeof(DelayedLoadPanelDesigner))]
	[ParseChildren(true)]
	[PersistChildren(false)]
	public class DelayedLoadPanel : BaseComplexControl
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		public DelayedLoadPanel()
		{
			if (!this.get_IsDesignMode())
			{
				if (TA.Turbo.TPage.Current != null)
				{
					TA.Turbo.TPage.Current.Init += new EventHandler(TPage_Init);
					TA.Turbo.TPage.Current.Load += new EventHandler(TPage_Load);
				}
			}

			this.Controls.Add(this.Initial.Container);
			this.Controls.Add(this.Content.Container);
		}
		#endregion
		#region EVENTS
		/// <summary>
		/// Raised when the client requests the contents of this panel to be displayed.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public ServerEvent<EventArgs> Display
		{
			get
			{
				return this.GetServerEvent<EventArgs>("Display");
			}
		}
		/// <summary>
		/// Raised when the client has received the contents of this panel and has finished displaying them.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public ClientEvent DisplayComplete
		{
			get
			{
				return this.GetEvent<ClientEvent>("DisplayComplete");
			}
		}
		#endregion
		#region PROPS
		#region DEF
		protected static new Properties _clientProperties = Define(BaseComplexControl._clientProperties,
			new BasePropertyDefinition[]
		  {
		    new PropertyDefinition<bool>("Displayed", "D", false),
		  });
		public override Properties ClientProperties
		{
			get
			{
				return _clientProperties;
			}
		}
		#endregion
		/// <summary>
		/// Gets or sets a flag which indicates whether the contents of this control are rendered.
		/// </summary>
		[DefaultValue(false)]
		public bool Displayed
		{
			get
			{
				return this.GetProperty<bool>("Displayed");
			}
			set
			{
				bool changed = !object.Equals(this.ViewState["Displayed"], value);

				this.ViewState["Displayed"] = value;

				if (changed && this._initDone)
				{
					this.UpdateControls();
				}
			}
		}
		/// <summary>
		/// The template to be used for initial markup, which is rendered if <see cref="Displayed"/> is false.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Browsable(false)]
		public SingleInstanceTemplate Initial { get { return this._initial; } }
		/// <summary>
		/// The template which contains the main contents of this panel.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Browsable(false)]
		public SingleInstanceTemplate Content { get { return this._content; } }
		#endregion
		#region METHODS
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		UpdatePanel _upd;
		SingleInstanceTemplate _initial = new SingleInstanceTemplate("Initial"),
			_content = new SingleInstanceTemplate("Content");
		bool _initDone;
		#endregion
		#region METHODS
		#region INIT
		/// <summary>
		/// Init.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			this.Initial.Init();
			this.Content.Init();

			this._initDone = true;
		}
		/// <summary>
		/// Init.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void TPage_Init(object sender, EventArgs e)
		{
			Control container = this.Parent;

			this._upd = new UpdatePanel();
			int index = container.Controls.IndexOf(this);
			container.Controls.AddAt(index, this._upd);
			this._upd.Controls.Add(this);

			this.UpdateControls();

			if (string.IsNullOrEmpty(this.Display.PostScenarioId))
			{
				this.Display.PostScenarioId = TPage.EmptyPostScenarioId;
			}
		}

		private void UpdateControls()
		{
			this.Initial.Container.Visible = !this.Displayed;
			this.Content.Container.Visible = this.Displayed;

			if (this.Displayed)
			{
				if (TPage.CurrentScenario != null && TPage.CurrentScenario.PostMode == PostMode.Ajax)
				{
					//foreach (IClientId clientId in this.TPage.AllClientIds)
					//{
					//  if (this.Content.Container.IsAscendantOf(clientId.Control) && clientId.Control.Visible)
					//  {
					//    this.TPage.RegisterScript(clientId.Control.UniqueID, clientId.GetScript(), false);
					//  }
					//}

					TPage.CurrentScenario.Ensure(this._upd);
				}

				if (!this.Content.Container.Visible)
				{
					Control c = this.Content.Container;
					do
					{
						if (c.Parent is DelayedLoadPanel)
						{
							c.Visible = true;
						}
						c = c.Parent;
					}
					while (!c.Visible);
				}
			}
		}
		/// <summary>
		/// Resets the state of this control to the saved version when re-using the page.
		/// </summary>
		protected internal override void Reset()
		{
			base.Reset();

			// the Displayed prop is reset directly; UpdateControls was not called - call it now
			this.UpdateControls();
		}
		void TPage_Load(object sender, EventArgs e)
		{
		}
		/// <summary>
		/// Registers client resource files which are necessary for the proper operation of this control on the client.
		/// </summary>
		protected internal override void RegisterIncludes(IncludeCollection includes)
		{
			base.RegisterIncludes(includes);

			includes.Add(new ScriptResourceInclude("TA.Turbo.Res.JS.DelayedLoadPanel.js", typeof(DelayedLoadPanel)));
		}
		#endregion
		#region EVENTS
		/// <summary>
		/// Raises events.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="argument"></param>
		public override void RaiseEvent(string name, string argument)
		{
			switch (name)
			{
				case "Display":
					this.OnDisplay(EventArgs.Empty);
					break;
				default:
					base.RaiseEvent(name, argument);
					break;
			}
		}
		/// <summary>
		/// Raises the <see cref="Display"/> event.
		/// </summary>
		/// <param name="e"></param>
		protected virtual void OnDisplay(EventArgs e)
		{
			this.Displayed = true;
			this.Display.Raise(this, e);
		}
		#endregion
		#region RENDER
		/// <summary>
		/// Returns true if the name attribute is required, otherwise false.
		/// </summary>
		/// <returns></returns>
		protected override bool IsNameAttributeRendered()
		{
			return true;
		}
		/// <summary>
		/// Add all attributes to render.
		/// </summary>
		/// <param name="writer"></param>
		protected override void AddAttributesToRender(HtmlTextWriter writer)
		{
			base.AddAttributesToRender(writer);
		}
		#endregion
		#endregion
		#endregion
	}
}
